#!/usr/bin/env python3
# Copyright (c) 2022 maminjie <canpool@163.com>
# SPDX-License-Identifier: MulanPSL-2.0

"""
Open Build Service API Wrapper
Execute command through the 'osc api -x '
As a supplement to osc command
Reference to https://build.opensuse.org/apidocs/index
"""

import os
import sys
import argparse
import logging

logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)

if sys.platform != "linux":
    logging.warning("The running environment only supports linux")
    sys.exit(1)

__version__ = "0.1"

project_template = """<project name="{project}">
  <title/>
  <description/>
  <person userid="{userid}" role="maintainer"/>
</project>"""

package_template = """
<package name="{package}" project="{project}">
  <title/>
  <description/>
</package>"""


def _do_x(req):
    os.system("osc api -X {}".format(req))


def obs_whois():
    with os.popen("osc whois 2>/dev/null | awk -F ':' '{print $1}'") as f:
        line = f.readline()
        return line.strip('\n') if line else None


def do_about(args):
    print("version {}".format(__version__))
    _do_x("GET /about")


def do_arch(args):
    _do_x("GET /architectures")


def do_token(args):
    """
    GET /person/<userid>/token
    POST /person/<userid>/token
    DELETE /person/<userid>/token/<id>
    """
    base_url = "/person/{userid}/token".format(userid=args.userid)
    if args.c:
        _do_x("POST {}".format(base_url))
    elif args.delete:
        _do_x("DELETE {}/{id}".format(base_url, id=args.delete))
    else:
        _do_x("GET {}".format(base_url))


def do_project_create(args):
    """PUT /source/<project>/_meta"""
    user = obs_whois()
    if not user:
        logging.error("unknown obs user")
    else:
        meta_data = project_template.format(project=args.project, userid=user)
        _do_x("PUT /source/{}/_meta --data '{}'".format(args.project, meta_data))


def do_project_copy(args):
    """POST /source/<project>?cmd=copy"""
    if not args.oproject:
        logging.error("need origin project")
    else:
        _do_x("POST '/source/{}?cmd=copy&oproject={}'".format(args.project, args.oproject))


def do_project(args):
    if args.cmd in ('create', 'c'):
        do_project_create(args)
    elif args.cmd in ('copy', 'cp'):
        do_project_copy(args)
    else:
        logging.error("unknown cmd '{}', can use 'osc' do it".format(args.cmd))


def do_package_create(args):
    """PUT /source/<project>/<package>/_meta"""
    meta_data = package_template.format(project=args.project, package=args.package)
    _do_x("PUT /source/{}/{}/_meta --data '{}'".format(args.project, args.package, meta_data))


def do_package_upload(args):
    """PUT /source/<project>/<package>/<filename>"""
    if not args.file:
        logging.error("need file")
    else:
        _do_x("PUT /source/{}/{}/{}".format(args.project, args.package, args.file))


def do_package(args):
    if args.cmd in ('create', 'c'):
        do_package_create(args)
    elif args.cmd in ('upload',):
        do_package_upload(args)
    else:
        logging.error("unknown cmd '{}', can use 'osc' do it".format(args.cmd))


def do_flag_set(args):
    """
    POST /source/<project>?cmd=set_flag
    POST /source/<project>/<package>?cmd=set_flag
    """
    if args.pkg:
        url = "/source/{}/{}?cmd=set_flag".format(args.project, args.pkg)
    else:
        url = "/source/{}?cmd=set_flag".format(args.project)
    if args.flag:
        url += "&flag={}".format(args.flag)
    else:
        logging.error("flag is mandatory")
        return
    if args.repo:
        url += "&repository={}".format(args.repo)
    if args.arch:
        url += "&arch={}".format(args.arch)
    url += "&status={}".format("enable" if args.status else "disable")
    _do_x("POST '{}'".format(url))


def do_flag_get(args):
    logging.error("not supported")


def do_flag(args):
    if args.cmd in ('set', 's'):
        do_flag_set(args)
    elif args.cmd in ('get', 'g'):
        do_flag_get(args)
    else:
        logging.error("unknown cmd '{}', can use 'osc' do it".format(args.cmd))


def do_main(args):
    print("try -h/--help for more details.")


def main():
    parser = argparse.ArgumentParser(description="Open Build Service API Wrapper Command-line Tool")
    parser.set_defaults(func=do_main)

    subparsers = parser.add_subparsers(help="obs sub-commands")
    # about
    subparser = subparsers.add_parser("about", help="about obs api wrapper")
    subparser.set_defaults(func=do_about)
    # architectures
    subparser = subparsers.add_parser("arch", help="get a list of all known architectures")
    subparser.set_defaults(func=do_arch)
    # token
    subparser = subparsers.add_parser("token", help="user token", aliases=['t'])
    subparser.add_argument("userid", type=str, help="user name")
    group = subparser.add_mutually_exclusive_group()
    group.add_argument("-c", action="store_true", help="create token")
    group.add_argument("-d", "--delete", type=str, metavar="id", help="delete token")
    subparser.set_defaults(func=do_token)
    # project
    subparser = subparsers.add_parser("project", aliases=['prj'], formatter_class=argparse.RawTextHelpFormatter,
                                      help="obs project")
    subparser.add_argument("cmd", type=str, metavar="CMD",
                           help="project cmd: \n"
                                "  create (c): create a project\n"
                                "  copy (cp): copy the entire project\n"
                           )
    subparser.add_argument("project", type=str, metavar="PROJECT", help="project name")
    subparser.add_argument("-op", "--oproject", type=str, metavar="OPROJECT", help="origin project name")
    subparser.set_defaults(func=do_project)
    # package
    subparser = subparsers.add_parser("package", aliases=['pkg'], formatter_class=argparse.RawTextHelpFormatter,
                                      help="obs package")
    subparser.add_argument("cmd", type=str, metavar="CMD",
                           help="package cmd: \n"
                                "  create (c): create a package\n"
                                "  upload: upload file to package\n"
                           )
    subparser.add_argument("project", type=str, metavar="PROJECT", help="project name")
    subparser.add_argument("package", type=str, metavar="PACKAGE", help="package name")
    subparser.add_argument("-f", "--file", type=str, metavar="FILE", help="file name")
    subparser.set_defaults(func=do_package)
    # flag
    subparser = subparsers.add_parser("flag", aliases=['f'], formatter_class=argparse.RawTextHelpFormatter,
                                      help="obs flag")
    subparser.add_argument("cmd", type=str, metavar="CMD",
                           help="flag cmd: \n"
                                "  set (s): set flag of project or package\n"
                                "  get (g): get flag of project or package\n"
                           )
    subparser.add_argument("project", type=str, metavar="PROJECT", help="project name")
    subparser.add_argument("-p", "--pkg", type=str, metavar="PACKAGE", help="package name")
    subparser.add_argument("-r", "--repo", type=str, metavar="REPOSITORY", help="repository name")
    subparser.add_argument("-a", "--arch", type=str, metavar="ARCH", help="architecture name")
    subparser.add_argument("-f", "--flag", type=str, metavar="FLAG",
                           help="flag (build/publish/debuginfo/useforbuild), mandatory")
    subparser.add_argument("-s", "--status", action="store_true", help="enable status")
    subparser.set_defaults(func=do_flag)

    args = parser.parse_args()
    args.func(args)


if __name__ == "__main__":
    main()
